package com.huanghuai.retail.service.impl;


import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huanghuai.retail.common.R;
import com.huanghuai.retail.dto.*;
import com.huanghuai.retail.entity.*;
import com.huanghuai.retail.mapper.PORepositoryMapper;
import com.huanghuai.retail.service.*;
import com.huanghuai.retail.utils.OPRepositoryNumsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.huanghuai.retail.common.JacksonObjectMapper.FORMAT_DATE;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zjh
 * @since 2023-05-04
 */
@Slf4j
@Service
public class PORepositoryServiceImpl extends ServiceImpl<PORepositoryMapper, PORepository> implements IPORepositoryService {

    @Autowired
    private IPOGoodsService goodsService;

    @Autowired
    SInventoryService sInventoryService;

    @Autowired
    private InformationService informationService;
    @Autowired
    private StorageService storageService;
    @Autowired
    private TypeService typeService;

    @Transactional
    @Override
    public Boolean savePORepositoryAndGoods(AddPORepositoryDto poRepositoryDto) {

        //仓库id
        Long repId = poRepositoryDto.getRepId();
        PORepository poRepository = new PORepository();
        String billType = poRepositoryDto.getBillType();

        Integer integer = panDuanRpType(billType);
        //供货人 销售出库入库不为空
        if (integer==5&&poRepositoryDto.getDeliId()==null){
            return false;
        }
        if (integer==3&&poRepositoryDto.getDeliId()==null){
            return false;
        }
        //采购入库 供应商不为空
        if (integer==1&&poRepositoryDto.getDeliId()==null){
            return false;
        }
        String opRepNum = createOPRepNum(integer, poRepositoryDto.getRepId());
        //自动生成单据编号
        poRepository.setBillNum(opRepNum);
        //设置单据类型
        poRepository.setBillTypeId(integer);
        BeanUtils.copyProperties(poRepositoryDto, poRepository);
        //保存出入库订单基本信息
        boolean isPORep = this.save(poRepository);
        List<AddPOGoodsDto> poGoodsList = poRepositoryDto.getPoGoodsList();
        List<POGoods> poGoodsList1 = new ArrayList<>();
        if (poGoodsList != null && poGoodsList.size() != 0)
            poGoodsList.stream().map((item) -> {
                POGoods poGoods = new POGoods();
                BeanUtils.copyProperties(item, poGoods);
                poGoods.setPORepositoryId(poRepository.getPORepositoryId());
                poGoodsList1.add(poGoods);
                return item;
            }).collect(Collectors.toList());
        //保存出入库商品信息

        //出库时判断是否大于库存量
        if (poRepository.getBillTypeId() > 3) {
            for (AddPOGoodsDto poGoods : poGoodsList) {
                //库存-出库值
                int i = poGoods.getInventoryNumber() - poGoods.getAmount();
                if (i < 0) {
                    return false;
                }

                boolean b = sInventoryService.updateByProIdWithStorageId(new SInventory(null, poGoods.getGoodsId(), i, null, null, repId));
                if (!b) {
                    return false;
                }

            }
        } else
            //入库时
            for (AddPOGoodsDto poGoods : poGoodsList) {
                int i = poGoods.getAmount() + poGoods.getInventoryNumber();
                //库存加入库值
                boolean b = sInventoryService.updateByProIdWithStorageId(new SInventory(null, poGoods.getGoodsId(), i, i, null, repId));
                if (!b) {
                    return false;
                }

            }
        boolean isPOGood = goodsService.saveBatch(poGoodsList1);


        return isPOGood && isPORep;
    }

    public static String createOPRepNum(Integer integer, Long repId) {

        switch (integer) {
            case 1:
                return OPRepositoryNumsUtils.createRepNums(OPRepositoryNumsUtils.ODDNUM_CGRK, repId);
            case 2:
                return OPRepositoryNumsUtils.createRepNums(OPRepositoryNumsUtils.ODDNUM_QTRK, repId);
            case 3:
                return OPRepositoryNumsUtils.createRepNums(OPRepositoryNumsUtils.ODDNUM_XSTHRK, repId);
            case 4:
                return OPRepositoryNumsUtils.createRepNums(OPRepositoryNumsUtils.ODDNUM_CGTHCK, repId);
            case 5:
                return OPRepositoryNumsUtils.createRepNums(OPRepositoryNumsUtils.ODDNUM_XSCK, repId);
            case 6:
                return OPRepositoryNumsUtils.createRepNums(OPRepositoryNumsUtils.ODDNUM_QTCK, repId);
            default:
                return "没有该单据类型";

        }
    }

    public static Integer panDuanRpType(String s) {

        switch (s) {
            case "采购入库":
                return 1;
            case "其他入库":
                return 2;
            case "销售退货入库":
                return 3;
            case "采购退货":
                return 4;
            case "销售出库":
                return 5;
            case "其他出库":
                return 6;
            default:
                return 0;

        }
    }
    public static String typeIdToString(Integer typeId) {

        switch (typeId) {
            case 1:
                return "采购入库";
            case 2:
                return "其他入库";
            case 3:
                return "销售退货入库";
            case 4:
                return "采购退货";
            case 5:
                return "销售出库";
            case 6:
                return "其他出库";
            default:
                return "未知信息";

        }
    }
    @Override
    public R<Page> getPoGoodsDtoPage(Integer page, Integer pageSize, String startTime,
                                     String endTime, String[] typeNames, Integer[] storageIds,
                                     String[] billNums, Long[] goodsIds, Long[] typeIds, String[] shopNames) {
        // 订单-商品表 主要过滤条件
        LambdaQueryWrapper<POGoods> queryWrapper = new LambdaQueryWrapper<>();
        // 订单表过滤条件
        if (startTime != null || endTime != null || storageIds != null || billNums != null || typeNames != null) {
            //1.时间过滤
            LambdaQueryWrapper<PORepository> repositoryQueryWrapper = new LambdaQueryWrapper<>();
            if (!handleDate(startTime, endTime, repositoryQueryWrapper)) {
                return R.error("错误的日期格式!");
            }
            // 2. 仓库号
            if (ArrayUtil.isNotEmpty(storageIds)) {
                repositoryQueryWrapper.in(PORepository::getRepId, storageIds);
            }
            // 3. 单据类型
            if (ArrayUtil.isNotEmpty(typeNames)) {
                Integer[] billTypeIds = new Integer[typeNames.length];
                for (int i = 0; i < typeNames.length; i++) {
                    billTypeIds[i] = BillTypeEnum.getIdByName(typeNames[i]);
                }
                repositoryQueryWrapper.in(PORepository::getBillTypeId, billTypeIds);
            }
            // 4.单据编号
            if (ArrayUtil.isNotEmpty(billNums)) {
                repositoryQueryWrapper.in(PORepository::getBillNum, billNums);
            }
            List<PORepository> repositoryList = list(repositoryQueryWrapper);
            if (repositoryList.isEmpty()) {
                return R.error("暂无信息!");
            }
            //遍历 订单表
            List<Long> repositoryIds = new ArrayList<>();
            repositoryList.forEach(repository -> {
                repositoryIds.add(repository.getPORepositoryId());
            });
            if (!repositoryIds.isEmpty()) {
                queryWrapper.in(POGoods::getPORepositoryId, repositoryIds);
            }
        }
        if (goodsIds != null || typeIds != null || shopNames != null) {
            //商品表过滤条件
            LambdaQueryWrapper<PInformation> informationQueryWrapper = new LambdaQueryWrapper<>();
            // 5.货品编码  ---
            if (ArrayUtil.isNotEmpty(goodsIds)) {
                informationQueryWrapper.in(PInformation::getId, goodsIds);
            }
            // 6. 货品类别
            if (ArrayUtil.isNotEmpty(typeIds)) {
                informationQueryWrapper.in(PInformation::getTypeId, typeIds);
            }
            // 7.货品名称		----
            if (ArrayUtil.isNotEmpty(shopNames)) {
                informationQueryWrapper.in(PInformation::getName, shopNames);
            }
            List<PInformation> informationList = informationService.list(informationQueryWrapper);
            if (informationList.isEmpty()) {
                return R.error("暂无信息！");
            }
            //遍历商品表
            List<Long> goodsIdses = new ArrayList<>();
            informationList.forEach(pInformation -> {
                goodsIdses.add(pInformation.getId());
            });
            if (!goodsIdses.isEmpty()) {
                queryWrapper.in(POGoods::getGoodsId, goodsIdses);
            }
        }
        Page<POGoods> pageInfo = new Page<>(page, pageSize);
        goodsService.page(pageInfo, queryWrapper);
        // 分页DTO  或 DTO里的 records
        Page<PORepositoryDto> dtoPage = new Page<>();
        List<PORepositoryDto> dtoRecords = new ArrayList<>();
        BeanUtils.copyProperties(pageInfo, dtoPage);
        List<POGoods> records = pageInfo.getRecords();
        for (POGoods poGoods : records) {
            PORepositoryDto repositoryDto = new PORepositoryDto();
            //获取流水单号   里面-> 日期 仓库ID  单据类型   和 单据编号 业务时间
            repositoryDto.setGoodsId(poGoods.getGoodsId());
            Long poRepositoryId = poGoods.getPORepositoryId();
            PORepository repository = getById(poRepositoryId);

            // !待删除
            if (repository == null) {
                log.error("一个不存在的poRepositoryId， {}", poRepositoryId);
                continue;
            }
            LocalDate date = repository.getCreateTime();
            repositoryDto.setCreateTime(date);
            Long repIdOne = repository.getRepId();
            //编号
            String billNumOne = repository.getBillNum();
            repositoryDto.setBillNum(billNumOne);
            //仓库
            Storage storage = storageService.getById(repIdOne);
            String storageName = storage.getStorageName();
            repositoryDto.setRepName(storageName);
            //单据类型
            Integer billTypeIdOne = repository.getBillTypeId();
            Double money = poGoods.getMoney();
            Integer amount = poGoods.getAmount();

            if (billTypeIdOne >= 1 && billTypeIdOne <= 4) {
                repositoryDto.setPMoney(money);
                repositoryDto.setPAmount(amount);
                repositoryDto.setOMoney(0.0);
                repositoryDto.setOAmount(0);
            } else if (billTypeIdOne <= 6) {
                repositoryDto.setOMoney(money);
                repositoryDto.setOAmount(amount);
                repositoryDto.setPMoney(0.0);
                repositoryDto.setPAmount(0);
            } else {
                return R.error("未知的订单类型!");
            }
            repositoryDto.setBillName(BillTypeEnum.getNameById(billTypeIdOne));

            Long goodsIdOne = poGoods.getGoodsId();
            //获取商品ID  ->  类型ID  单位ID  规格型号  商品名称
            // 待删除
            PInformation information = informationService.getById(goodsIdOne);
            if (information == null) {
                log.error("一个不存在的oodsId， {}", goodsIdOne);
                continue;
            }
            //名称
            String nameOne = information.getName();
            repositoryDto.setShopName(nameOne);
            //类型
            Long typeIdOne = information.getTypeId();
            PType ptype = typeService.getById(typeIdOne);
            String nameTypeOne = ptype.getNameTwo();
            repositoryDto.setShopType(nameTypeOne);
            //单位
            String wrap = information.getWrap();
            repositoryDto.setWrap(wrap);
            //规格类型
            String specs = information.getSpecs();
            repositoryDto.setSpecs(specs);
            dtoRecords.add(repositoryDto);
        }
        dtoPage.setRecords(dtoRecords);
        return R.success(dtoPage);
    }

    @Override
    public R<Map> collectPORepository(String startTime, String endTime, String[] typeName,
                                      Integer[] storageId, String[] billNum, Long[] goodsId, Long[] typeId, String[] shopName) {

        int count = goodsService.count();
        R<Page> poGoodsDtoPage = getPoGoodsDtoPage(1, count, startTime,
                endTime, typeName, storageId,
                billNum, goodsId, typeId, shopName);
        Page data = poGoodsDtoPage.getData();
        List records = data.getRecords();
        Integer pAmounts = 0;
        Integer oAmounts = 0;
        Double pMoneys = 0.0;
        Double oMoneys = 0.0;
        for (Object record : records) {
            PORepositoryDto poRepositoryDto = (PORepositoryDto) record;
            String billName = poRepositoryDto.getBillName();
            Integer billTypeId = BillTypeEnum.getIdByName(billName);
            if (billTypeId == null){
                return R.error("订单类型有误");
            }
            if (billTypeId >= 1 && billTypeId <= 4) {
                pMoneys+=poRepositoryDto.getPMoney();
                pAmounts+=poRepositoryDto.getPAmount();
            } else if (billTypeId <= 6) {
                oMoneys+=poRepositoryDto.getOMoney(); 
                oAmounts+=poRepositoryDto.getOAmount();
            } else {
                return R.error("未知的订单类型!");
            }
        }
        Map<String, Map[]> list = new HashMap<>(2);
        Map<String, String> amountMaps[] = new HashMap[2];
        Map<String, String> moneyMaps[] = new HashMap[2];
        String[] amountKeys = {"入库数量","出库数量"};
        String[] moneyKeys = {"入库金额","出库金额 "};
        Object[] amountValues = {pAmounts,oAmounts};
        Object[] moneyValues = {pMoneys, oMoneys};
        for (int i = 0; i < 2; i++) {
            Map<String, String> amountMap = new HashMap<>();
            Map<String, String> moneyMap = new HashMap<>();
            amountMap.put("key", amountKeys[i]);
            amountMap.put("value", amountValues[i].toString());
            moneyMap.put("key", moneyKeys[i]);
            moneyMap.put("value", moneyValues[i].toString());
            amountMaps[i] = amountMap;
            moneyMaps[i] = moneyMap;
        }
        list.put("amount", amountMaps);
        list.put("money", moneyMaps);
        return R.success(list);
    }


    private boolean handleDate(String startTime, String endTime, LambdaQueryWrapper<PORepository> repositoryQueryWrapper) {
        try {
            if (StrUtil.isNotBlank(startTime)) {
                repositoryQueryWrapper.ge(PORepository::getCreateTime, FORMAT_DATE.parse(startTime));
            }
            if (StrUtil.isNotBlank(endTime)) {
                repositoryQueryWrapper.le(PORepository::getCreateTime, FORMAT_DATE.parse(endTime));
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public R<List<PORepository>> findAllBillNumber() {
        QueryWrapper<PORepository> queryWrapper = new QueryWrapper<>();

        queryWrapper.select("DISTINCT bill_num"); 
        List<PORepository> list = list(queryWrapper);

        if (list.isEmpty()) {
            return R.error("暂无信息");
        }

        return R.success(list);
    }



}
